package com.pine.manager.core;

import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.pine.common.util.json.JsonUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


/**
 * json中的字段值脱敏工具
 *
 * @author pine manage
 * @since 2024-08-14
 */
@Slf4j
public class DesensitizedOnJsonComponent {

    public static final Map<String, String> SENSITIZED_FIELD_MAP = new HashMap<>(16);
    static {
        SENSITIZED_FIELD_MAP.put("password", "******");
        SENSITIZED_FIELD_MAP.put("email", "******");
        SENSITIZED_FIELD_MAP.put("phone", "******");
        SENSITIZED_FIELD_MAP.put("idCard", "******");
    }

    private static final ObjectMapper MAPPER = JsonUtil.getObjectMapper();

    public static String desensitized(String json) {
        if (ObjectUtil.isEmpty(json)) {
            return json;
        }

        try {
            JsonNode node = MAPPER.readTree(json);
            // 更新节点
            updateNodes(node);

            return MAPPER.writeValueAsString(node);
        } catch (IOException e) {
            // 增强异常处理：记录日志并给出明确的错误处理策略
            log.error("Json读取失败，将返回原始JSON。", e);
            return json;
        }
    }

    private static void updateNodes(JsonNode node) {
        if (node.isObject()) {
            updateObjectNode((ObjectNode) node);
            Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
            fields.forEachRemaining(entry -> {
                updateNodes(entry.getValue());
            });
            return;
        }

        if (node.isArray()) {
            ArrayNode arrayNode = (ArrayNode) node;
            for (JsonNode jsonNode : arrayNode) {
                updateNodes(jsonNode);
            }
        }
    }


    /**
     * 更新ObjectNode
     *
     * @param objectNode ObjectNode
     */
    private static void updateObjectNode(ObjectNode objectNode) {
        SENSITIZED_FIELD_MAP.forEach((fieldName, newValue) -> {
            if (objectNode.has(fieldName)) {
                objectNode.put(fieldName, newValue);
            }
        });
    }

    /**
     * 添加需要脱敏的字段。
     *
     * @param fieldName              需要被替换的字段名
     * @param desensitizedFieldValue 替换后的字段值
     */
    public static void addSensitizedField(String fieldName, String desensitizedFieldValue) {
        SENSITIZED_FIELD_MAP.put(fieldName, desensitizedFieldValue);
    }

//    public static void main(String[] args) {
//        String json = "[{\"loginAccount\":\"admin\",\"password\":\"123456\"}]";
//
//        String result = DesensitizedOnJsonConvertor.desensitized(json);
//        System.out.println(result);
//
//        DesensitizedOnJsonConvertor.addSensitizedField("token", "******");
//        String json2 = "{\"data\":{\"loginAccount\":\"admin\",\"username\":\"系统管理员\",\"id\":1,\"token\":\"101caf6a-f5e7-4518-9a4c-e5556087c62b\",\"roles\":[{\"id\":1,\"code\":\"manager\",\"roleName\":\"管理员\",\"remark\":\"\"}]},\"code\":\"0\",\"logId\":\"a0f7c458d096431889bdf75a6ba4460d\",\"timestamp\":1722245147730}";
//        String result2 = DesensitizedOnJsonConvertor.desensitized(json2);
//        System.out.println(result2);
//    }
}
